package routing;

import geocoding.CustomNodes;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;

import android.location.Location;
import android.util.Log;

public class LandmarkMaker { 
	
	String TAG = "URN"; 
	
	ArrayList<Integer> landmarks = new ArrayList<Integer>();
	
	public ArrayList<Integer> makeLandmarks(CustomNodes cn) {

		
		for (int nodes=0; nodes<cn.getSize(); nodes++) {

			if (!cn.getHas_tags(nodes)) {
				continue; 
			}
			
			
			boolean add = false; 
			for (int tags=0; tags<cn.getValueSize(nodes); tags++) {
				
//				Log.d(TAG, "      key, value: " + cn.getTag(nodes, tags) + " , " + cn.getValue(nodes, tags)); 
				
				if (cn.getTag(nodes, tags).equals("historic")
						|| cn.getTag(nodes, tags).equals("tourism")
						|| cn.getTag(nodes, tags).equals("building")
						|| cn.getTag(nodes, tags).equals("shop")
						|| cn.getTag(nodes, tags).equals("name")
//						|| cn.getTag(nodes, tags).equals("natural")
						
						) 
//				if (filterLandmarks) 
				
				{

					add = true; 
					continue; 
				}
			}	
			
			if (add) {
				landmarks.add(nodes);
			}
			
		}
		



		return landmarks;  
		
	}
	
	
	public Trip getPossibleLandmarksForSegment(CustomNodes cn, Trip myTrip) {
		
		ArrayList<Integer> landmarks = myTrip.getLandmarks(); 
		ArrayList<Segment> segments = myTrip.getSegments(); 
		
		
		for (Segment s : segments) {
			
			HashSet<Integer> closeLandmarks = new HashSet<Integer>();
			ArrayList<Node> nodesInSegment = s.getNodes(); 
			
			for (int n = 0; n< nodesInSegment.size(); n++) {
				
				Location nl = new Location("x");
				nl.setLatitude(cn.getDlati(nodesInSegment.get(n).getId())); 
				nl.setLongitude(cn.getDlongi(nodesInSegment.get(n).getId()));
				
				
				for (int l = 0; l< landmarks.size(); l++) {
					
					Location ll = new Location("x");
					ll.setLatitude(cn.getDlati(landmarks.get(l)));
					ll.setLongitude(cn.getDlongi(landmarks.get(l)));
					
					
					
					
					if (ll.distanceTo(nl) < 30) {
//						Log.d(TAG, "Segment " + s.getId() + " comparing " + cn.getOsmID(nodesInSegment.get(n).getId()) + " with " 
//								+ cn.getOsmID(landmarks.get(l)) + " , dist is " + ll.distanceTo(nl));
						
						
						closeLandmarks.add(landmarks.get(l)); 
						
					}
					
				}
				
			}
			
			s.setCloseLandmarkIds(closeLandmarks); 
			

		}
		myTrip.setSegments(segments); 
		return myTrip; 
		
	}
	
	public Trip assignNodes2Landmarks (Trip myTrip, CustomNodes cn) {
		
		Log.d(TAG, "start");
		
		Compass compass = new Compass(); 
		
		ArrayList<Segment> segments = myTrip.getSegments(); 
		
		for (int seg = 0; seg < segments.size(); seg++) {
			
			Segment s = segments.get(seg); 
			
			HashSet<Integer> closeLandmarks = s.getCloseLandmarkIds(); 
			ArrayList<Node> nodesInSegment = s.getNodes(); 
			
			// Add the first node of the next segment for isValid check
			if (seg != segments.size()-1) {
			nodesInSegment.add(segments.get(seg+1).getNodes().get(0));
			}
			
			
			Iterator<Integer> it = closeLandmarks.iterator(); 
			
			while (it.hasNext()) {
				
				// get the closest node (within this segment) for the landmark and assign it to the landmark
				
				int lmid = it.next(); 
				int closestNodeID = -1; 
				float closestDist = 9999; 
				
				Location lml = new Location("x");
				lml.setLatitude(cn.getDlati(lmid));
				lml.setLongitude(cn.getDlongi(lmid));
				

				
				for (int no = 0; no < nodesInSegment.size()-1; no++) {
					
					Node n = nodesInSegment.get(no); 
					Node nn = nodesInSegment.get(no+1);
					
					Location nl = new Location("x");
					nl.setLatitude(cn.getDlati(n.getId()));
					nl.setLongitude(cn.getDlongi(n.getId()));
					
					Location nnl = new Location("x");
					nnl.setLatitude(cn.getDlati(nn.getId()));
					nnl.setLongitude(cn.getDlongi(nn.getId()));
					
					Location ll = new Location("x");
					ll.setLatitude(cn.getDlati(lmid));
					ll.setLongitude(cn.getDlongi(lmid));
					
					float btn = nl.bearingTo(nnl); 
					float btl = nl.bearingTo(ll); 
					
					Log.d(TAG, "checking correctAngle for node"  + cn.getOsmID(n.getId()) + " nextnode: " + cn.getOsmID(nn.getId()) 
							+ " landmark " + cn.getOsmID(lmid));
					
					Log.d(TAG, "" + compass.correctAngle90(btn, btl));
					
					if (nl.distanceTo(lml) < closestDist && compass.correctAngle90(btn, btl)) {
						
						closestDist = nl.distanceTo(lml); 
						closestNodeID = n.getId(); 

					}
					
				}
				
				
				if (closestNodeID != -1) {
					Landmark l = new Landmark();
					l.setInternID(lmid); 
					l.setAssignedNodeInternID(closestNodeID); 
					l.setOsmID(Integer.valueOf(cn.getOsmID(lmid)));
					l.setAssignedNodeOSMID(Integer.valueOf(cn.getOsmID(closestNodeID))); 
					
					
					for (int t= 0; t < cn.getValueSize(lmid); t++) {
						
						String key = cn.getTag(lmid, t); 
						String value = cn.getValue(lmid, t); 
						l.addTag(key, value); 
						
					}
					
	
					s.addLandmark(l); 
				
				}
				
			}
			
			
			
		}
		Log.d(TAG, "end");
		myTrip.setSegments(segments); 
		return myTrip; 
	}
	
	public Trip assignLandmarks2Nodes (Trip myTrip, CustomNodes cn) {
		
		Log.d(TAG, "start");
		
		ArrayList<Segment> segments = myTrip.getSegments(); 
		for (Segment s : segments) {
			
			ArrayList<Node> nodes = s.getNodes(); 
			ArrayList<Landmark> landmarks = s.getLandmarks(); 
			
			for (Node n : nodes) {
				
				int nodeID = n.getId(); 
				
				for (Landmark l : landmarks) {
					
					if (l.getAssignedNodeInternID() == nodeID) {
						
						n.addLandmark(l); 
						
					}
					
				}
				
				
			}
			
			
			s.setNodes(nodes); 
			
		}
		
		myTrip.setSegments(segments); 
		
		return myTrip; 
	}
	
	public Trip createLandmarkDirectionText (Trip myTrip, CustomNodes cn) {
		
		Compass compass = new Compass();
		
		ArrayList<Segment> segments = myTrip.getSegments(); 
		for (Segment s : segments) {
			
			Log.d(TAG, "Segment: " + s.getId());
			ArrayList<Node> nodes = s.getNodes();
			
			for (int n= 0; n<nodes.size()-1; n++) {
				
				Node thisNode = nodes.get(n); 
				Node nextNode = nodes.get(n+1); 
				
				ArrayList<Landmark> landmarks = thisNode.getLandmarks(); 
				for (Landmark l : landmarks) {
					
					
					Location thisLocation = new Location("x");
					thisLocation.setLatitude(cn.getDlati(thisNode.getId()));
					thisLocation.setLongitude(cn.getDlongi(thisNode.getId())); 
					
					String dir = compass.getDirection(thisLocation, l.getInternID(), nextNode.getId(), cn);
					
					l.setDirectionText(dir + "vorbei an"); 
					
					
					if (!l.isSilent()) {
						Log.d(TAG, " Von Node " + cn.getOsmID(thisNode.getId()) + " " + dir + " vorbei an " + l.lmToString());
					}	
				}
				
				thisNode.setLandmarks(landmarks); 
				
				
			}
			
			s.setNodes(nodes); 
			
			
			
		}
		
		myTrip.setSegments(segments); 
		return myTrip; 
	}
	
	public Trip removeDuplicateLandmarksPerNode (Trip myTrip, CustomNodes cn) {
		
		ArrayList<Segment> segments = myTrip.getSegments(); 
		
		for (Segment s : segments) {
			
			ArrayList<Node> nodesInSegment = s.getNodes(); 
			
			for (Node n : nodesInSegment) {
				
				ArrayList<Landmark> landmarks = n.getLandmarks(); 				
				
				for (int l1 = 0; l1< landmarks.size(); l1++) {
					
					for (int l2 = 0; l2< landmarks.size(); l2++) {
						
						if (l1 == l2) {
							continue; 
						}
						
						if (landmarks.get(l1).getTags().toString().equals(landmarks.get(l2).getTags().toString())) {
							
							
							Log.d(TAG, "removine duplicate lm " + landmarks.get(l2).lmToString());
							landmarks.get(l2).setSilent(true);							
						}
						
						
						
					}
					

					
					
					
				}


				
				n.setLandmarks(landmarks); 
				
				
			}
			
			s.setNodes(nodesInSegment); 
		}
		
		
		
		return myTrip; 
	}
	
	
	public void filterLandmarks (int nodeID, CustomNodes cn) {
		
		
		
	}
	
	

}
